#pragma once
#include "RenderingPrefix.h"
#include "Resource/VertexFactory.h"

namespace Alice
{
    class MaterialRenderProxy;
    class PrimitiveSceneInfo;
    /**
     * A batch mesh element definition.
     */
    struct FMeshBatchElement
    {
        uint32 FirstIndex;
        /** When 0, IndirectArgsBuffer will be used. */
        uint32 NumPrimitives;

        /** Number of instances to draw.  If InstanceRuns is valid, this is actually the number of runs in InstanceRuns. */
        uint32 NumInstances;
        uint32 BaseVertexIndex;
        uint32 MinVertexIndex;
        uint32 MaxVertexIndex;
        int32 UserIndex;
        float MinScreenSize;
        float MaxScreenSize;
    };
    /**
     * A batch of mesh elements, all with the same material and vertex buffer
     */
    struct FMeshBatch
    {
        std::vector<FMeshBatchElement> mMeshBatchElements;
        /** LOD index of the mesh, used for fading LOD transitions. */
        int8 LODIndex;
	    /** Vertex factory for rendering, required. */
        const VertexFactory* mVertexFactory;
	    /** Material proxy for rendering, required. */
        const MaterialRenderProxy* mMaterialRenderProxy;
        FMeshBatch();
    };
    class FStaticMeshBatch:public  FMeshBatch
    {
    public:
        PrimitiveSceneInfo*mPrimitiveSceneInfo;
        FStaticMeshBatch(PrimitiveSceneInfo*inPrimitiveSceneInfo,const FMeshBatch&inMeshBatch);
    };
    /**
     * FStaticMeshBatch data which is InitViews specific. Stored separately for cache efficiency.
     */
    class FStaticMeshBatchRelevance
    {
    public:
        /** Starting offset into continuous array of command infos for this mesh in FPrimitiveSceneInfo::CachedMeshDrawCommandInfos. */
        FMeshPassMask mCommandInfosMask;
        
        /** The index of the mesh in the scene's static meshes array. */
        int32 Id;

        /** The screen space size to draw this primitive at */
        float ScreenSize;

        /** Number of elements in this mesh. */
        uint16 NumElements;

        /* Every bit corresponds to one MeshPass. If bit is set, then FPrimitiveSceneInfo::CachedMeshDrawCommandInfos contains this mesh pass. */
        uint16 CommandInfosBase;
        /** Computes index of cached mesh draw command in FPrimitiveSceneInfo::CachedMeshDrawCommandInfos, for a given mesh pass. */
        int32 GetStaticMeshCommandInfoIndex(EMeshPass::Type MeshPass) const;
    };
    /**
     * An interface used to query a primitive for its static elements.
     */
    class FStaticPrimitiveDrawInterface
    {
    public:
        /**
          * Reserve memory for specified number of meshes in order to minimize number of allocations inside DrawMesh.
          */
        virtual void ReserveMemoryForMeshes(int32 MeshNum) = 0;
        virtual void DrawMesh(
            const FMeshBatch& Mesh,
            float ScreenSize
            ) = 0;
    };
    /** An implementation of FStaticPrimitiveDrawInterface that stores the drawn elements for the rendering thread to use. */
    class FBatchingSPDI : public FStaticPrimitiveDrawInterface
    {
    public:
        PrimitiveSceneInfo*mPrimitiveSceneInfo;
        FBatchingSPDI(PrimitiveSceneInfo*inPrimitiveSceneInfo):mPrimitiveSceneInfo(inPrimitiveSceneInfo){}
        virtual void ReserveMemoryForMeshes(int32 MeshNum) override;
        virtual void DrawMesh(const FMeshBatch& inMesh, float inScreenSize) final override;
    };
}
